<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>类型约束</title>

 </head>
 <body><div class="manualnavbar" style="text-align: center;">
 <div class="prev" style="text-align: left; float: left;"><a href="language.oop5.object-comparison.html">对象比较</a></div>
 <div class="next" style="text-align: right; float: right;"><a href="language.oop5.late-static-bindings.html">后期静态绑定</a></div>
 <div class="up"><a href="language.oop5.html">类与对象</a></div>
 <div class="home"><a href="index.html">PHP Manual</a></div>
</div><hr /><div id="language.oop5.typehinting" class="sect1">
  <h2 class="title">类型约束</h2>
  <p class="para">
   PHP 5 可以使用类型约束。函数的参数可以指定必须为对象（在函数原型里面指定类的名字），接口，数组（PHP
   5.1 起）或者 <span class="type"><a href="language.types.callable.html" class="type callable">callable</a></span>（PHP 5.4 起）。不过如果使用 <span class="type"><a href="language.types.null.html" class="type NULL">NULL</a></span>
   作为参数的默认值，那么在调用函数的时候依然可以使用 <span class="type"><a href="language.types.null.html" class="type NULL">NULL</a></span> 作为实参。
  </p>
  
  <p class="para">
   如果一个类或接口指定了类型约束，则其所有的子类或实现也都如此。
  </p>
  
  <p class="para">
   类型约束不能用于标量类型如 <span class="type"><a href="language.types.integer.html" class="type int">int</a></span> 或
   <span class="type"><a href="language.types.string.html" class="type string">string</a></span>。<a href="language.oop5.traits.html" class="link">Traits</a> 也不允许。
  </p>

  <div class="example" id="example-223">
   <p><strong>Example #1 类型约束示例</strong></p>
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #FF8000">//如下面的类<br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">MyClass<br /></span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;测试函数<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;第一个参数必须为&nbsp;OtherClass&nbsp;类的一个对象<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">test</span><span style="color: #007700">(</span><span style="color: #0000BB">OtherClass&nbsp;$otherclass</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #0000BB">$otherclass</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">var</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;另一个测试函数<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;第一个参数必须为数组&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">test_array</span><span style="color: #007700">(array&nbsp;</span><span style="color: #0000BB">$input_array</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">print_r</span><span style="color: #007700">(</span><span style="color: #0000BB">$input_array</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;第一个参数必须为递归类型<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">test_interface</span><span style="color: #007700">(</span><span style="color: #0000BB">Traversable&nbsp;$iterator</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #0000BB">get_class</span><span style="color: #007700">(</span><span style="color: #0000BB">$iterator</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #FF8000">/**<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;第一个参数必须为回调类型<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">public&nbsp;function&nbsp;</span><span style="color: #0000BB">test_callable</span><span style="color: #007700">(</span><span style="color: #0000BB">callable&nbsp;$callback</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">$data</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">call_user_func</span><span style="color: #007700">(</span><span style="color: #0000BB">$callback</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">$data</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /></span><span style="color: #FF8000">//&nbsp;OtherClass&nbsp;类定义<br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">OtherClass&nbsp;</span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;</span><span style="color: #0000BB">$var&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'Hello&nbsp;World'</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
   </div>

   <div class="example-contents"><p>
    函数调用的参数与定义的参数类型不一致时，会抛出一个可捕获的致命错误。
   </p></div>
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #FF8000">//&nbsp;两个类的对象<br /></span><span style="color: #0000BB">$myclass&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">MyClass</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$otherclass&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">OtherClass</span><span style="color: #007700">;<br /><br /></span><span style="color: #FF8000">//&nbsp;致命错误：第一个参数必须是&nbsp;OtherClass&nbsp;类的一个对象<br /></span><span style="color: #0000BB">$myclass</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">test</span><span style="color: #007700">(</span><span style="color: #DD0000">'hello'</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">//&nbsp;致命错误：第一个参数必须为&nbsp;OtherClass&nbsp;类的一个实例<br /></span><span style="color: #0000BB">$foo&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">stdClass</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$myclass</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">test</span><span style="color: #007700">(</span><span style="color: #0000BB">$foo</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">//&nbsp;致命错误：第一个参数不能为&nbsp;null<br /></span><span style="color: #0000BB">$myclass</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">test</span><span style="color: #007700">(</span><span style="color: #0000BB">null</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">//&nbsp;正确：输出&nbsp;Hello&nbsp;World&nbsp;<br /></span><span style="color: #0000BB">$myclass</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">test</span><span style="color: #007700">(</span><span style="color: #0000BB">$otherclass</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">//&nbsp;致命错误：第一个参数必须为数组<br /></span><span style="color: #0000BB">$myclass</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">test_array</span><span style="color: #007700">(</span><span style="color: #DD0000">'a&nbsp;string'</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">//&nbsp;正确：输出数组<br /></span><span style="color: #0000BB">$myclass</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">test_array</span><span style="color: #007700">(array(</span><span style="color: #DD0000">'a'</span><span style="color: #007700">,&nbsp;</span><span style="color: #DD0000">'b'</span><span style="color: #007700">,&nbsp;</span><span style="color: #DD0000">'c'</span><span style="color: #007700">));<br /><br /></span><span style="color: #FF8000">//&nbsp;正确：输出&nbsp;ArrayObject<br /></span><span style="color: #0000BB">$myclass</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">test_interface</span><span style="color: #007700">(new&nbsp;</span><span style="color: #0000BB">ArrayObject</span><span style="color: #007700">(array()));<br /><br /></span><span style="color: #FF8000">//&nbsp;正确：输出&nbsp;int(1)<br /></span><span style="color: #0000BB">$myclass</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">test_callable</span><span style="color: #007700">(</span><span style="color: #DD0000">'var_dump'</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
   </div>

   <div class="example-contents"><p>
    类型约束不只是用在类的成员函数里，也能使用在函数里：
   </p></div>
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #FF8000">//&nbsp;如下面的类<br /></span><span style="color: #007700">class&nbsp;</span><span style="color: #0000BB">MyClass&nbsp;</span><span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;</span><span style="color: #0000BB">$var&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #DD0000">'Hello&nbsp;World'</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #FF8000">/**<br />&nbsp;*&nbsp;测试函数<br />&nbsp;*&nbsp;第一个参数必须是&nbsp;MyClass&nbsp;类的一个对象<br />&nbsp;*/<br /></span><span style="color: #007700">function&nbsp;</span><span style="color: #0000BB">MyFunction&nbsp;</span><span style="color: #007700">(</span><span style="color: #0000BB">MyClass&nbsp;$foo</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span><span style="color: #0000BB">$foo</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">var</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #FF8000">//&nbsp;正确<br /></span><span style="color: #0000BB">$myclass&nbsp;</span><span style="color: #007700">=&nbsp;new&nbsp;</span><span style="color: #0000BB">MyClass</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">MyFunction</span><span style="color: #007700">(</span><span style="color: #0000BB">$myclass</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
   </div>

   <div class="example-contents"><p>
    类型约束允许 NULL 值：
   </p></div>
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #FF8000">/*&nbsp;接受&nbsp;NULL&nbsp;值&nbsp;*/<br /></span><span style="color: #007700">function&nbsp;</span><span style="color: #0000BB">test</span><span style="color: #007700">(</span><span style="color: #0000BB">stdClass&nbsp;$obj&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">NULL</span><span style="color: #007700">)&nbsp;{<br /><br />}<br /><br /></span><span style="color: #0000BB">test</span><span style="color: #007700">(</span><span style="color: #0000BB">NULL</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">test</span><span style="color: #007700">(new&nbsp;</span><span style="color: #0000BB">stdClass</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code></div>
   </div>

  </div>
 </div><hr /><div class="manualnavbar" style="text-align: center;">
 <div class="prev" style="text-align: left; float: left;"><a href="language.oop5.object-comparison.html">对象比较</a></div>
 <div class="next" style="text-align: right; float: right;"><a href="language.oop5.late-static-bindings.html">后期静态绑定</a></div>
 <div class="up"><a href="language.oop5.html">类与对象</a></div>
 <div class="home"><a href="index.html">PHP Manual</a></div>
</div></body></html>
